import random
from src.netWork.OOP.Node import Node as Node


class Connection(object):

    # downstream_node: Node
    # upstream_node: Node

    __slots__ = ('upstream_node', 'downstream_node', 'weight', 'gradient')

    def __init__(self, upstream_node, downstream_node):
        '''
        初始化联接，初始权重为一个很小的随机数
        :param upstream_node:
        :param downstream_node:
        '''

        self.downstream_node = downstream_node
        self.upstream_node = upstream_node
        self.weight = random.uniform(-0.1, 0.1)
        self.gradient = 0.0

    def calc_gradient(self):
        '''
        计算梯度
        :return:
        '''

        # ðEd / ðwji = xji * δj
        self.gradient = self.downstream_node.delta * self.upstream_node.output

    def get_gradient(self):
        return self.gradient

    def update_weight(self, rate):
        '''
        根据梯度更新权重
        :param rate:
        :return:
        '''
        self.calc_gradient()

        # wnew = wold + η * Δ
        self.weight += rate * self.gradient

    def __str__(self):
        '''
        打印连接信息
        '''
        return '(%u-%u) -> (%u-%u) = %f' % (
            self.upstream_node.layer_index,
            self.upstream_node.node_index,
            self.downstream_node.layer_index,
            self.downstream_node.node_index,
            self.weight)
